%{
#include<stdio.h>
#include<string.h>
#include<stdlib.h>


int linhaErro = 1;
void yyerror(const char *str)
{
        //fprintf(stderr,"error: %s\n",str);
	printf("Erro na compilacao - analise sintatica - %dª linha valida\n", linhaErro);
}
 
int yywrap()
{
        return 1;
}


FILE *arquivoPython;
int identacao = 0;

%}

%union {
	char identificador[1024];
}


%token if_ repeat_ for_ wait_ penup pendown turnleft turnright direction go gox goy reset pencolor penwidth canvassize canvascolor inteiro variavel while_ abre_par fecha_par abre_cha fecha_cha virgula to_ true_ false_ op_maior op_menor op_igual op_mais op_menos op_vezes op_div op_and op_or forward backward write_ frase
%%

programa:
			{int i;for(i=0; i<=identacao;i++) fprintf(arquivoPython,"  ");}comando {linhaErro++;}comando_recursivo {printf("compilacao realizada com sucesso.\n"); fprintf(arquivoPython, "    end\n\nend\n\nGtk.init\nwindow = Compiler.new\nGtk.main"); fclose(arquivoPython);}
	;

comando_recursivo:/*vazio*/
			| {int i;for(i=0; i<=identacao;i++) fprintf(arquivoPython,"  ");}comando{linhaErro++;} comando_recursivo	
			;

bloco:
			comando_recursivo
	;

comando_if:
			if_ abre_par expressao_booleana fecha_par abre_cha {identacao++;fprintf(arquivoPython, "if (%s)\n", $<identificador>3);} bloco fecha_cha {			fprintf(arquivoPython, "end\n");
				
				printf("comando if foi executado\n");}
		;

comando_repeat:
	repeat_ expressao_matematica {
			if (atoi($<identificador>2) < 0) printf("erro na compilacao - valor abaixo de 0 para o comando repeat.\n");}
	 		abre_cha {
				
				fprintf(arquivoPython, "%s.repeat {\n", $<identificador>2);}
			 bloco fecha_cha { fprintf(arquivoPython, "}\n");
				
				printf("comando repeat foi executado\n");
				}
	;


comando_for:
	for_ atribuicao_mat to_ expressao_matematica abre_cha 
		{	identacao++;
			char parteVariavel[30];
			char parteExpressao[30];
			char* res;
			res = strtok($<identificador>2, "?");
			strcpy(parteVariavel, res);			
			res = strtok(NULL, "?");
			strcpy(parteExpressao, res);
			printf("%s\n", res);
			fprintf(arquivoPython, "for %s in %s..%s+1\n",parteVariavel, parteExpressao, $<identificador>4); 


		}
		bloco fecha_cha {fprintf(arquivoPython, "end\n");
			;printf("comando for foi executado\n");}
	;


comando_wait:
	 wait_ expressao_matematica {
				fprintf(arquivoPython,"wait(%s)\n", $<identificador>2);
				printf("comando wait foi executado\n")
				}
	;

comando_while:
	  while_ abre_par expressao_booleana fecha_par abre_cha{fprintf(arquivoPython, "while (%s) do\n",$<identificador>3);} 
		bloco fecha_cha {

				fprintf(arquivoPython, "end\n");
					
				printf("comando while foi executado\n");
			}
	;

comando_penup:
	 penup {fprintf(arquivoPython, "penup\n"); printf("comando penup foi executado\n");}
	;

comando_pendown:
	 pendown {fprintf(arquivoPython, "pendown\n");printf("comando pendown foi executado\n");}
	;

comando_turnleft:
	turnleft expressao_matematica {
		if ((atoi($<identificador>2) > 360)||(atoi($<identificador>2) < 0))
			printf("erro na compilação - valor inadequado para angulo.\n");
         	else{
			fprintf(arquivoPython, "turnleft(%s.to_i)\n", $<identificador>2);
			printf("comando turnleft foi executado\n");
		    }
	}
	;

comando_turnright:
	turnright expressao_matematica {
		if ((atoi($<identificador>2) > 360)||(atoi($<identificador>2) < 0))
			printf("erro na compilação - valor inadequado para ângulo.\n");
	        else{
			fprintf(arquivoPython,"turnright(%s.to_i)\n", $<identificador>2);	
			printf("comando turnright foi executado\n");
		    }
		} 
	;

comando_go:
	go expressao_matematica virgula expressao_matematica {								   
		fprintf(arquivoPython, "go %s, %s\n", $<identificador>2, $<identificador>4);
	printf("comando go foi executado\n");
	  }
	;

comando_gox:
	gox expressao_matematica {
		fprintf(arquivoPython, "gox %s\n", $<identificador>2);
		printf("comando gox foi executado\n");
	}
	;

comando_goy:
	goy expressao_matematica {
		fprintf(arquivoPython, "goy %s\n", $<identificador>2);
		printf("comando goy foi executado\n");
	}
	;

comando_reset:
	reset {
		fprintf(arquivoPython, "reset\n");
		printf("comando reset executado\n");}
	;

comando_pencolor:
	pencolor expressao_matematica virgula expressao_matematica virgula expressao_matematica {
		if ((atoi($<identificador>2)>255 )||( atoi($<identificador>4) > 255 )||( atoi($<identificador>6) >255 )||( atoi($<identificador>2) <0 )||( atoi($<identificador>4) < 0 )||( atoi($<identificador>6) <0))
			printf("erro na compilação - valor da tripla rgb excede os limites\n.");
		else
			fprintf(arquivoPython, "estdo_cor_atual_caneta = %s %s %s", $<identificador>2, $<identificador>3, $<identificador>4);
		printf("comando pencolor foi executado\n");
	}
	;

comando_penwidth:
	penwidth expressao_matematica{
		fprintf(arquivoPython, "penwidth(int(%s))\n", $<identificador>2);
		printf("comando penwidth foi executado\n");}
	;

comando_canvassize:
	canvassize expressao_matematica virgula expressao_matematica {fprintf(arquivoPython, "estdo_tamanho_tela = %s",$<identificador>2);printf("comando canvassize foi executado\n");}
	;

comando_canvascolor:
	canvascolor expressao_matematica virgula expressao_matematica virgula expressao_matematica {
		if ((atoi($<identificador>2)>255 )||( atoi($<identificador>4) > 255 )||( atoi($<identificador>6) >255 )||( atoi($<identificador>2) <0 )||( atoi($<identificador>4) < 0 )||( atoi($<identificador>6) <0))
			printf("erro na compilação - valor da tripla rgb excede os limites\n.");
		else
			fprintf(arquivoPython, "estdo_cor_atual_tela = %s %s %s", $<identificador>2, $<identificador>3, $<identificador>4);
		printf("comando canvascolor foi executado\n");
		}

	;

comando_forward:
		forward expressao_matematica {
			fprintf(arquivoPython, "forward(%s.to_i)\n", $<identificador>2);
			printf("comando forward foi executado\n");}
		;

comando_backward:
		backward expressao_matematica {
			fprintf(arquivoPython, "backward(%s.to_i)\n", $<identificador>2);
			printf("comando backward foi executado\n");}
		;

comando_write:
		write_ frase {
				int i;
				for (i=1; i < strlen($<identificador>1); i++)
					if ($<identificador>1[i] == '\"') 
						$<identificador>1[i] ='\0';
				fprintf(arquivoPython, "print_string(%s)\n", ($<identificador>1+1));
				printf("comando write foi executado\n");
	}
	;

valor_inteiro:
			variavel {strcpy($<identificador>$,($<identificador>1+1));}
			|inteiro {strcpy($<identificador>$,$<identificador>1);}
			| op_menos inteiro {strcat($<identificador>$, "-"); strcat($<identificador>$, $<identificador>1);}
			;

valor_booleano:
			valor_inteiro {strcpy($<identificador>$,$<identificador>1);}
			|true_ {strcpy($<identificador>$,$<identificador>1);}
			|false_ {strcpy($<identificador>$,$<identificador>1);}
			;

comando:
		atribuicao_mat
		|comando_if
		|comando_repeat
		|comando_for
		|comando_wait
		|comando_while
		|comando_penup
		|comando_pendown
		|comando_turnleft
		|comando_turnright
		|direction   
		|comando_go
		|comando_gox
		|comando_goy
		|comando_reset 
		|comando_pencolor
		|comando_penwidth
		|comando_canvassize
		|comando_canvascolor
		|comando_forward
		|comando_backward
		|comando_write
		    ;		

expressao_matematica:
		    expressao_matematica op_mais expm2 {strcat($<identificador>1, "+"); strcat($<identificador>1, $<identificador>3); strcpy($<identificador>$,$<identificador>1);}
		    |expressao_matematica op_menos expm2 {strcat($<identificador>1, "-"); strcat($<identificador>1, $<identificador>3); strcpy($<identificador>$,$<identificador>1);}
		    | expm2 {strcpy($<identificador>$,$<identificador>1);}
		    ;

expm2:
	expm2 op_vezes expm3 {strcat($<identificador>1, "*"); strcat($<identificador>1, $<identificador>3); strcpy($<identificador>$,$<identificador>1);}
	| expm2 op_div expm3 {strcat($<identificador>1, "/"); strcat($<identificador>1, $<identificador>3); strcpy($<identificador>$,$<identificador>1);}
	| expm3 {strcpy($<identificador>$,$<identificador>1);}
	;

expm3:
	abre_par expressao_matematica fecha_par {strcat($<identificador>2, ")"); strcpy($<identificador>$, "("); strcat($<identificador>$,$<identificador>2);}
	| valor_inteiro {strcpy($<identificador>$,$<identificador>1); }
	;

atribuicao_mat:
	   variavel op_igual expressao_matematica{
		fprintf(arquivoPython, "%s = %s\n",($<identificador>1+1), $<identificador>3);
		printf("comando atribuicao_mat foi executado\n");
		strcpy($<identificador>$,($<identificador>1+1));
		strcat($<identificador>$,"?");
		strcat($<identificador>$, $<identificador>3);
		strcat($<identificador>$,"?");
		}
	   ;

expressao_booleana:
			expressao_booleana op_igual op_igual expb2{strcat($<identificador>1, "=="); strcat($<identificador>1, $<identificador>3); strcpy($<identificador>$,$<identificador>1);} 
			| expressao_booleana op_and expb2{strcat($<identificador>1, " and "); strcat($<identificador>1, $<identificador>3); strcpy($<identificador>$,$<identificador>1);} 
			| expressao_booleana op_or expb2 {strcat($<identificador>1, " or "); strcat($<identificador>1, $<identificador>3); strcpy($<identificador>$,$<identificador>1);} 
			| expb2 {strcpy($<identificador>$,$<identificador>1);}
			;

expb2:
	expb2 op_maior expb3 {strcat($<identificador>1, ">"); strcat($<identificador>1, $<identificador>3); strcpy($<identificador>$,$<identificador>1);}
	|expb2 op_menor expb3{strcat($<identificador>1, "<"); strcat($<identificador>1, $<identificador>3); strcpy($<identificador>$,$<identificador>1);}
	|expb3{strcpy($<identificador>$,$<identificador>1);}
	;

expb3:
		abre_par expressao_booleana fecha_par{strcat($<identificador>2, ")"); strcpy($<identificador>$, "("); strcat($<identificador>$,$<identificador>2);}
		| valor_booleano {strcpy($<identificador>$,$<identificador>1);}
		;

%%
#include <stdio.h>



int main( )
{
	
	arquivoPython = fopen("codigo.rb", "w");
	fprintf(arquivoPython,"#!/usr/bin/ruby\n\nrequire 'lib'\n\nclass Compiler < Gtk::Window\n\ndef run_cmds\n\n");
 	return yyparse();
}
